from datetime import datetime
from typing import Dict, List, Tuple, Optional
from Assignment_and_Grading.course_task_classes import Assignment
from Course_Management_and_Enrollment.course_task_classes import Course
from User_Management.user_classes import Student, User

class GradingSystem:
    def __init__(self, lms=None):
        # 成绩记录格式: {course_id: {student_id: {task_id: score, ...}, ...}}
        self.grade_records = {}
        # 分数等级映射
        self.grade_scale = {90: "A", 80: "B", 70: "C", 60: "D", 0: "F"}
        # 任务权重配置
        self.task_weights = {}
        # 初始化lms属性
        self.lms = lms

    def grade_assignment_by_ids(self, student_id, course_id, assignment_id, score):
        """通过ID为学生的作业评分(用于UI层调用)"""
        try:
            # 查找学生对象
            student = None
            for user in User.all_users():
                if isinstance(user, Student) and user.student_id == student_id:
                    student = user
                    break
            
            if not student:
                raise ValueError(f"Student ID not found: {student_id}")
            
            
            # 查找课程对象 - 优化查找逻辑
            course = None
            for user in User.all_users():
                if hasattr(user, 'courses_teaching'):
                    for c in user.courses_teaching:
                        if hasattr(c, 'course_id') and c.course_id == course_id:
                            course = c
                            break
                if course:
                    break
                if hasattr(user, 'enrolled_courses'):
                    for c in user.enrolled_courses:
                        if hasattr(c, 'course_id') and c.course_id == course_id:
                            course = c
                            break
                if course:
                    break
            
            if not course:
                raise ValueError(f"Course ID not found: {course_id}")
            
            # 查找作业对象
            assignment = None
            if hasattr(course, 'course_assignments'):
                for a in course.course_assignments:
                    if getattr(a, 'assignment_id', None) == assignment_id or getattr(a, 'assignable_id', None) == assignment_id:
                        assignment = a
                        break
            
            if not assignment:
                raise ValueError(f"Assignment ID not found: {assignment_id}")
            
            # 调用原始的评分方法
            self.grade_assignment(student, assignment, score)
            return True
            
        except Exception as e:
            print(f"Error grading by ID: {str(e)}")
            raise
        

    def grade_assignment(self, student, assignment, score):
        """为学生的作业评分"""
        try:
            # 获取必要的ID信息
            student_id = getattr(student, 'student_id', getattr(student, 'user_id', str(student)))
            assignment_id = getattr(assignment, 'assignment_id', getattr(assignment, 'assignable_id', None))
            course_id = assignment.course.course_id
            
            # 检查作业是否存在
            if not assignment_id:
                raise ValueError("The assignment ID is None.")
                
            # 检查学生是否已提交作业
            if not hasattr(assignment, 'submissions') or student_id not in assignment.submissions:
                raise ValueError(f"Student {student_id} has not submitted the assignment.")
        
            # 保存成绩到学生对象的submitted_assignments
            updated = False
            for submitted in student.submitted_assignments:
                if submitted["assignment_id"] == assignment_id:
                    submitted["score"] = score
                    # 检测并保留现有状态文本语言
                    current_status = submitted.get("status", "submitted")
                    submitted["status"] = "graded" if current_status.lower() == "graded" else "submitted"
                    updated = True
                    break
        
            # 如果没找到,创建新的提交记录 - 关键修复:使用中文状态
            if not updated:
                if not hasattr(student, 'submitted_assignments'):
                    student.submitted_assignments = []
                
                submission_data = assignment.submissions[student_id]
                status_lang = "graded" if submission_data.get("status", "").lower() in ["graded", "已评分"] else "submitted"

                student.submitted_assignments.append({
                    "assignment_id": assignment_id,
                    "course_id": course_id,
                    "content": submission_data.get("content", ""),
                    "submit_time": submission_data.get("submit_time"),
                    "is_late": submission_data.get("is_late", False),
                    "score": score,
                    "status": status_lang  # 使用中文状态确保状态正确
                })
        
            if hasattr(assignment, 'submissions') and student_id in assignment.submissions:
                assignment.submissions[student_id]["score"] = score
                current_status = assignment.submissions[student_id].get("status", "submitted")
                assignment.submissions[student_id]["status"] = "graded" if current_status.lower() == "graded" else "submitted"
        
            # 同时更新到grade_records中
            self.record_grade(
                student_id=student_id,
                course_id=course_id,
                task_id=assignment_id,
                score=score
            )
        
            # 更新学生的课程总成绩
            total_score = self.calculate_total_score(student_id, assignment.course)
            student.grades[assignment.course] = total_score
        
            # 保存数据
            if hasattr(self, 'lms') and hasattr(self.lms, 'save_data'):
                self.lms.save_data(force=True)
        
            print(f"作业 {assignment.title} 评分完成: 学生 {student_id} 得分 {score}")
        except Exception as e:
            print(f"评分过程中出错: {str(e)}")
            raise


    def calculate_total_score(self, student_id: str, course: Course) -> float:
        """计算学生课程总成绩(作业平均分)"""
        total = 0
        count = 0
        
        if hasattr(course, '_course_assignments'):
            for assignment in course._course_assignments:
                # 修复:正确读取字典中的score字段
                if student_id in assignment.submissions and assignment.submissions[student_id].get("score") is not None:
                    # 计算相对于满分的百分比
                    percentage = (assignment.submissions[student_id]["score"] / assignment.total_points) * 100
                    # 应用权重(如果有)
                    weight = self._get_task_weight(course.course_id, assignment.assignable_id)
                    total += percentage * weight
                    count += 1
        
        # 同时检查grade_records中的成绩
        if course.course_id in self.grade_records and student_id in self.grade_records[course.course_id]:
            for task_id, score in self.grade_records[course.course_id][student_id].items():
                # 避免重复计算
                is_assignment_score = False
                if hasattr(course, '_course_assignments'):
                    for assignment in course._course_assignments:
                        if assignment.assignable_id == task_id:
                            is_assignment_score = True
                            break
                
                if not is_assignment_score:
                    weight = self._get_task_weight(course.course_id, task_id)
                    total += score * weight
                    count += 1
        
        return total / count if count > 0 else 0

    def record_grade(self, student_id: str, course_id: str, task_id: str, score: float) -> str:
        """记录成绩"""
        # 初始化课程和学生的成绩记录
        if course_id not in self.grade_records:
            self.grade_records[course_id] = {}
        if student_id not in self.grade_records[course_id]:
            self.grade_records[course_id][student_id] = {}

        # 验证分数范围(0-100)
        score = max(0, min(100, score))
        self.grade_records[course_id][student_id][task_id] = score
        return f"Grade recorded: Student {student_id}, Task {task_id}, Score {score}"

    def calculate_course_grade(self, student: Student, course: Course) -> float:
        """计算课程最终成绩(加权平均分)"""
        course_id = course.course_id
        student_id = student.student_id

        # 从calculate_total_score获取综合成绩
        average_score = self.calculate_total_score(student_id, course)
        return average_score

    def generate_grade_report(self, student: Student) -> str:
        """生成学生成绩报告"""
        # 报告头部
        report = f"# Student Grade Report\n"
        report += f"Student Name: {student.username}\n"
        report += f"Student ID: {student.student_id}\n"
        report += f"Generation time: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n"
        report += f"==============================\n\n"
        
        # 检查是否有成绩记录
        has_grades = False
        for course_id in self.grade_records:
            if student.student_id in self.grade_records[course_id]:
                has_grades = True
                break
        
        if not has_grades and (not hasattr(student, 'grades') or not student.grades):
            return report + "⚠️  No grade records available\n"
        
        # 遍历学生的成绩记录
        if hasattr(student, 'grades'):
            all_grades = []
            for course, grade in student.grades.items():
                # 处理课程名称显示
                course_name = getattr(course, 'course_name', f"Course {getattr(course, 'course_id', 'Unknown')}")
                course_id = getattr(course, 'course_id', 'Unknown')
                
                report += f"📚 Course Name: {course_name}\n"
                report += f"Course ID: {course_id}\n"
                report += f"Final Grade: {grade:.2f}\n"
                all_grades.append(grade)
                
                # 获取该课程的详细成绩信息
                if course_id in self.grade_records and student.student_id in self.grade_records[course_id]:
                    report += "  Assignment Grades:\n"
                    task_scores = self.grade_records[course_id][student.student_id]
                    for task_id, score in task_scores.items():
                        weight = self._get_task_weight(course_id, task_id)
                        weight_text = f" (Weight: {weight})" if weight != 1.0 else ""
                        report += f"    - Task {task_id}: {score:.2f}{weight_text}\n"
                
                report += "   ------------------------------\n\n"
            
            # 计算并添加平均成绩
            if all_grades:
                avg_grade = sum(all_grades) / len(all_grades)
                report += f"📊 Overall Average Grade: {avg_grade:.2f}\n"
        
        return report

    def load_grade_data(self, grade_data: dict) -> None:
        """加载成绩数据"""
        # 初始化空的成绩记录结构
        self.grade_records = {}
    
        # 遍历JSON中的成绩记录并转换为内部格式
        # 适配实际的data.json格式: {"COURSE_id": {"STU_id": {"TASK_x": score}}}
        for course_id, students_data in grade_data.items():
            if course_id not in self.grade_records:
                self.grade_records[course_id] = {}
        
            for student_id, tasks_data in students_data.items():
                if student_id not in self.grade_records[course_id]:
                    self.grade_records[course_id][student_id] = {}
                
                # 直接使用现有的任务ID和成绩
                for task_id, score in tasks_data.items():
                    self.grade_records[course_id][student_id][task_id] = score
                     
    def _get_task_weight(self, course_id: str, task_id: str) -> float:
        """获取任务权重"""
        if course_id in self.task_weights and task_id in self.task_weights[course_id]:
            return self.task_weights[course_id][task_id]
        return 1.0
        
    def set_task_weight(self, course_id: str, task_id: str, weight: float) -> None:
        """设置任务权重"""
        if course_id not in self.task_weights:
            self.task_weights[course_id] = {}
        self.task_weights[course_id][task_id] = weight
        
    def batch_import_grades(self, course_id: str, grades_data: dict) -> str:
        """批量导入成绩数据"""
        success_count = 0
        error_count = 0
        
        for student_id, tasks_data in grades_data.items():
            for task_id, score in tasks_data.items():
                try:
                    self.record_grade(student_id, course_id, task_id, float(score))
                    success_count += 1
                except Exception:
                    error_count += 1
        
        return f"Batch import completed: {success_count} grades imported successfully, {error_count} errors."
